package milkyway.hightech.banking;

import milkyway.hightech.conditions.GiroAccountConditions;
import milkyway.hightech.exceptions.TransactionNotAllowedException;
import milkyway.hightech.money.Currency;
import milkyway.hightech.money.Money;
import milkyway.hightech.timer.TimeEmitter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Observable;
import milkyway.hightech.entry.Entry;
import milkyway.hightech.exceptions.NotEnoughMoneyException;

public class GiroAccount extends Account
{
    private GiroAccountConditions conditions;
    
    /**
     * creates a new giro account
     * @param accountNumber the number of this account
     * @param accountHolder the holder of this account
     * @param accountType the description of this account
     * @param creditInterest the current rate of credit interest
     * @param debitInterest the current rate of debit interest
     */
    public GiroAccount(int accountNumber, String accountHolder, Currency currency, GiroAccountConditions conditions, Calendar calendar)
    {
	super(accountNumber, accountHolder, currency, calendar);
	this.conditions = conditions;
    }
    
    @Override
    public void update(Observable o, Object obj)
    {
	if(TimeEmitter.getInstance().getCalendar().getTime().getDate() == 1)
	{
	    setChanged();
	    notifyObservers(this);
	}
    }
    
    /**
     * enters the given amount on debit and assures that
     * the account ballance will not be less than zero
     * @param amount the amount of money which should be entered on debid
     * @param reasonOfTransfer the description of this transaction
     */
    @Override
    public void enterOnDebit(Money amount, String reasonOfTransfer)
    {
	BigInteger b = getAccountBalance().subtract(amount.getValue());
	int dispo = b.compareTo(conditions.getDispo().negate());
	int signum = amount.getValue().signum();
	
	if(signum <= 0)
	    throw new TransactionNotAllowedException(getAccountNumber() + ", on " + TimeEmitter.getInstance().getCalendar().getTime()
		    + ", could not be applied");
	else if(dispo == -1)
	    throw new NotEnoughMoneyException(getAccountNumber() + ", on " + TimeEmitter.getInstance().getCalendar().getTime()
		    + ", could not be applied");
	else
	    update(-1, amount, reasonOfTransfer);
    }

    /**
     * pays the current interest on credit/debit //verzinsen
     */
    @Override
    public void payInterest()
    {
	BigDecimal d = new BigDecimal(getAccountBalance().divide(BigInteger.valueOf(100)));

	if(d.signum() >= 1)
	{
	    d = d.multiply(BigDecimal.valueOf(conditions.getCreditInterest()));
	    this.enterOnCredit(new Money(d.toBigInteger(), money.getCurrency()), "pay interest");
	}
	else
	{
	    d = d.multiply(BigDecimal.valueOf(conditions.getCreditInterest()));
	    this.enterOnDebit(new Money(d.toBigInteger().negate(), money.getCurrency()), "pay interest");
	}
    }
}